import { Component, Input, OnInit, SimpleChanges, OnChanges } from '@angular/core';
import { forEach as _forEach, remove as _remove } from 'lodash-es';
import {
    ExternalMultiUploadMergeInput,
    ExternalMultiUploadVerifyInput,
    FileInfoDto,
    FileObjectConfigDto,
    FileUploadServiceProxy,
    IdAndOrderOfGuid,
    MultipartUploadServiceProxy,
    NewFileSortNumberInput,
    SelectFromLibraryInput,
    SetFileStatusInput,
    SwapSortNumberInput
} from "@shared/service-proxies/service-proxies";
import { AppConsts } from '@shared/AppConsts';
import { finalize } from 'rxjs/operators';
import { FileItem } from 'ng2-file-upload';
import { TokenService, MessageService } from 'abp-ng2-module';
import { FileUploadHelper } from '@shared/helpers/FileUploadHelper';
import { AppLocalizationService } from '@app/shared/common/localization/app-localization.service';
import { UploadItemData } from './upload-Item-data';
import { AppNotifyService } from '@shared/utils/service/app-notify.service';
import { FileUpdateModalComponent } from './file-update-modal.component';
import { AppBsModalService } from '@shared/common/appBsModal/app-bs-modal.service';
import { FindingFileItem } from '../file-finder/file-finder-options';
import { MultipartUploadHelper } from '../multipart-upload/multipart-upload-helper';
import { ChunkContainer, Status } from '../multipart-upload/multipart-upload-option';

export interface readyFile{
    file: any,
    dataUrl: string,
    icon: string,
    exName: string,
    isImage: boolean
}
@Component({
    selector: 'batch-upload-item',
    templateUrl: './batch-upload-item.component.html'
})
export class BatchUploadItemComponent implements OnInit, OnChanges{
    @Input() customKey: string;
    @Input() contentId: string;
    @Input() templateInfo: FileObjectConfigDto;
    @Input() ctrlDisabled: boolean;
    @Input() autoSyncBySelf: boolean;      // 编辑表单上是否显示自动同步的勾选框
    @Input() refreshValue:string;  // 刷新请求

    @Input() isTemporary: boolean;

    loading: boolean = false;
    permission: boolean = false;

    fileInfos: UploadItemData[] = [];

    private _multipartUploadHelper: MultipartUploadHelper;

    get showProgressBar():boolean{
        return this._multipartUploadHelper.showHashProgress || this._multipartUploadHelper.showMerging
        || [Status.pause, Status.uploading, Status.error].includes(this._multipartUploadHelper.status);
    }

    get uploadProgress(): number {
		return this._multipartUploadHelper.uploadProgress;
	}
    get uploadingFile(): ChunkContainer {
		return this._multipartUploadHelper.container;
	}
    get ReadyFiles(): ChunkContainer[] {
		return this._multipartUploadHelper.uploadingFileQueue;
	}

    constructor(
        private _fileUploadServiceProxy: FileUploadServiceProxy,
        private _tokenService: TokenService,
        private message: MessageService,
        private notify: AppNotifyService,
        private _appLocalizationService: AppLocalizationService,
        private _modalService: AppBsModalService,
        private _multipartUploadService: MultipartUploadServiceProxy) {

        this._multipartUploadHelper = new MultipartUploadHelper(notify, _tokenService);
    }
    ngOnInit(): void {
        this.permission = !this.ctrlDisabled;      
        this.InitializeUpload();
    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes['contentId']) {
            if (this.contentId) {
                this.initFile();
            }
        }

        if (changes['ctrlDisabled']){
            this.permission = !changes['ctrlDisabled'].currentValue;
        }

        if (changes['refreshValue']) {
            if (!this.refreshValue) return;
            this.initFile();
        }
    }
    
    private InitializeUpload() {
        this._multipartUploadHelper.Initialize(4, {
            uploaderUrl: AppConsts.remoteServiceBaseUrl + '/B/FileUpload/UploadFile',
            partUploaderUrl: AppConsts.remoteServiceBaseUrl + '/B/EditorFile/PartUpload',
            singleUploaderOnBuildItemForm: (fileItem, form) => {
                form.append('contentId', this.contentId);
                form.append('customKey', this.customKey);
                form.append('alias', this.templateInfo.alias);
                form.append('isTemporary', this.isTemporary);
            },
            uploadedCallback: (fileItem) => {
                var data = new UploadItemData();
                data.init(fileItem);
                data.icon = FileUploadHelper.getIcon(data.exName);
                this.fileInfos.push(data);
            },
            verifyFunction: (t) => {
                return this._multipartUploadService.externalMultiUploadVerify(t);
            },
            getVerifyInput: (fileContainer) => {
                return new ExternalMultiUploadVerifyInput({
                    fileHash: fileContainer.hash,
                    fileName: fileContainer.file.name,
                    isTemporary: this.isTemporary,
                    contentId: this.contentId,
                    customKey: this.customKey,
                    alias: this.templateInfo.alias
                });
            },
            getMergeRequestInput: () => {
                return new ExternalMultiUploadMergeInput({
                    fileHash: this._multipartUploadHelper.container.hash,
                    fileName: this._multipartUploadHelper.container.file.name,
                    fileSize: this._multipartUploadHelper.container.file.size,
                    dimensions: this._multipartUploadHelper.container.dimensions,
                    count: this._multipartUploadHelper.chunks.length,
                    isTemporary: this.isTemporary,
                    contentId: this.contentId,
                    customKey: this.customKey,
                    alias: this.templateInfo.alias
                });
            },
            mergeRequestFunction: (t) => {
                return this._multipartUploadService.externalMultiUploadMerge(t);
            }
        });
    }

    //----文件上传-----

    fileChangeEvent(event: any): void {
        if (!this.permission) {
            event.target.value = null;
            return;
        }

        if (event.target.files) {
            let newFiles:File[] = [];
            let files = event.target.files;
            for (const iterator of files) {
                newFiles.push(iterator);
            }
            event.target.value = null;

            for (let i = 0; i < newFiles.length; i++) {
                let file = newFiles[i];
                if (!FileUploadHelper.check(file.name, this.templateInfo.exNames, file.size,
                     this.templateInfo.maxSize, this.notify, this._appLocalizationService)) {
                                    
                    let item = this._multipartUploadHelper.getUploadingFileItem(file);
                    this._multipartUploadHelper.uploadingFileQueue.push(item);
                }
            }

            this._multipartUploadHelper.handleUpload();
        }
    }

    //----文件上传 end-----

    abortUpload() {
        // 异步调度，不一定能停下来
        if(this._multipartUploadHelper.status === Status.uploading){
            this._multipartUploadHelper.handlePause();
        }

        this._multipartUploadHelper.uploadingFileQueue.length = 0;
        this._multipartUploadHelper.container = null;
    }

    cancelUploadingItem() {
        if(this._multipartUploadHelper.status === Status.uploading){
            this._multipartUploadHelper.handlePause();
        }
        this._multipartUploadHelper.container = null;
    }
    cancelFromQueue(index: number) {
        this._multipartUploadHelper.cancelFromQueue(index);
    }

    getUrl(fileInfo: UploadItemData) {
        return FileUploadHelper.getUrl(fileInfo.fileUrl);
    }
    getDownUrl(fileInfo: UploadItemData) {
        return FileUploadHelper.getDownUrl(fileInfo.exName, fileInfo.fileUrl);
    }

    getSmallUrl(file: FileInfoDto) {
        return FileUploadHelper.getSmallUrl(file.fileUrl, 100, 80);
    }

    lookOver(picurl:string) {
        abp.event.trigger(AppConsts.EventName.showImageView, picurl);
    }


    initFile() {
        this.loading = true;
        this._fileUploadServiceProxy.getFileInfos(this.contentId, this.templateInfo.alias)
            .pipe(finalize(() => this.loading = false))
            .subscribe(result => {
                let data: UploadItemData[] = [];
                result.forEach(item => {
                    let d = new UploadItemData(item);
                    d.icon = FileUploadHelper.getIcon(item.exName);
                    data.push(d);
                });

                this.fileInfos = data;
            });
    }



    //-----Actions------
    update(fileInfo: UploadItemData) {
        const bsModalRef = this._modalService.show(FileUpdateModalComponent, {
            backdrop: 'static', class: 'modal-lg'
        });
        bsModalRef.content.configure({
            id: fileInfo.id,
            customKey: this.customKey,
            multiply: true,
            autoSyncBySelf: this.autoSyncBySelf,
            config: this.templateInfo
        });
        bsModalRef.content.shown();
        bsModalRef.content.reloadList = () => {
            this.initFile();
        };
    }

    delete(fileInfo: UploadItemData) {
        this.message.confirm(this._appLocalizationService.l("YesDelete"), null, (isConfirmed) => {
            if (isConfirmed) {
                this.loading = true;
                this._fileUploadServiceProxy.deleteFile(fileInfo.id, this.customKey)
                    .pipe(finalize(() => this.loading = false))
                    .subscribe(result => {
                        this.initFile();
                        this.notify.success(this._appLocalizationService.l('SuccessfullyDeleted'));
                    });
            }
        });
    }

    batchDelete(){
        this.message.confirm("是否删除全部数据", null,
            (isConfirmed) => {
                if (!isConfirmed) return;

                let totolCount = this.fileInfos.length;
                let count = 0;
                this.fileInfos.forEach((item,index)=>{
                    this._fileUploadServiceProxy.deleteFile(item.id, this.customKey)
                        .subscribe(result => {
                            count++;
                            if(count === totolCount){
                                this.initFile();
                                this.notify.success(this._appLocalizationService.l('SuccessfullyDeleted'));
                            }
                        },error=>{
                            count++;
                            if(count === totolCount){
                                this.initFile();
                                this.notify.success(this._appLocalizationService.l('SuccessfullyDeleted'));
                            }
                        });
                });
            })
    }

    releaseState(fileInfo: UploadItemData) {
        this.loading = true;
        let input = new SetFileStatusInput();
        input.idList = [fileInfo.id];
        input.isActive = true;
        input.customKey = this.customKey;

        this._fileUploadServiceProxy.setStatus(input)
            .pipe(finalize(() => this.loading = false))
            .subscribe(result => {
                this.initFile();
                this.notify.success(this._appLocalizationService.l('ReleaseSuccessfully'));
            });
    }

    cancelReleaseState(fileInfo: UploadItemData) {
        this.loading = true;
        let input = new SetFileStatusInput();
        input.idList = [fileInfo.id];
        input.isActive = false;
        input.customKey = this.customKey;

        this._fileUploadServiceProxy.setStatus(input)
            .pipe(finalize(() => this.loading = false))
            .subscribe(result => {
                this.initFile();
                this.notify.success(this._appLocalizationService.l('CancelReleaseSuccessfully'));
            });
    }

    changeOrder($event, item: UploadItemData) {
        let order = item.order;
        let regu = /^[1-9]\d*$/;
        if (!regu.test($event.target.value)) {
            $event.target.value = order;
            return;
        }

        let newOrder = parseInt($event.target.value);
        if (isNaN(newOrder)) {
            $event.target.value = order;
            return;
        } else if (newOrder !== order) {
            let isSuccess = false;
            this.loading = true;

            let input = new NewFileSortNumberInput();
            input.id = item.id;
            input.newNumber = newOrder;
            input.customKey = this.customKey;

            this._fileUploadServiceProxy.setNewSorNumber(input)
                .pipe(finalize(() => {
                    this.loading = false;
                    if (!isSuccess) {
                        $event.target.value = order;
                    }
                }))
                .subscribe(result => {
                    isSuccess = true;
                    item.order = newOrder;
                    this.fileInfos.sort(function (a, b) {
                        return a.order - b.order;
                    });
                    this.notify.success(this._appLocalizationService.l('OrderSuccessSuccessfully'));
                });
        }
    }

    pickupFile(){
        abp.event.trigger('abp.ckeditor.filefinder', { editor:null, multiSelect: true, callback: (list: FindingFileItem[])=>{
            list.forEach(item =>{
                let fileUrl = item.fileUrl;
                let fileName = item.fileName;

                if (!FileUploadHelper.checkExName(fileName, this.templateInfo.exNames)) {
                    let exNameArr = this.templateInfo.exNames.split('|');
                    this.notify.error(fileName + '：' + this._appLocalizationService.l('File_Invalid_Type_Error', exNameArr.join('、')));
                    return;
                }

                let input = new SelectFromLibraryInput({
                    alias : this.templateInfo.alias,
                    customKey :this.customKey,
                    contentId: this.contentId,
                    fileUrl:  fileUrl, 
                    fileLength: item.size,
                    sha1: item.sha1,
                    isTemporary : this.isTemporary,
                    dimensions: item.dimensions
                });
                this._fileUploadServiceProxy.uploadFile2(input)
                    .subscribe(result=>{
                        var data = new UploadItemData();
                        data.init(result);
                        data.icon = FileUploadHelper.getIcon(data.exName);
                        this.fileInfos.push(data);
                    });
            });
        } });
    }

    
    private move(fromIndex: number, toIndex: number) {
        if (fromIndex === toIndex) {
            return;
        }

        let a = this.fileInfos[fromIndex];
        let b = this.fileInfos[toIndex];

        this.loading = true;
        this._fileUploadServiceProxy.swapObjectSort(new SwapSortNumberInput({
            idOrderList: [
                new IdAndOrderOfGuid({
                    id: a.id,
                    order: b.order
                }),
                new IdAndOrderOfGuid({
                    id: b.id,
                    order: a.order
                })
            ]
        })).pipe(finalize(() => {
            this.loading = false;
        })).subscribe(result=>{
            this.initFile();
            this.notify.success(this._appLocalizationService.l('OrderSuccessSuccessfully'));
        })
    }
    upsort(item){
       let index = this.fileInfos.findIndex(t => t.id === item.id);
       if (index === 0) {
           this.notify.warn(this._appLocalizationService.l('AlreadyBeTheFirst'));
           return;
       }

       this.move(index, index - 1);
    }

    downSort(item){
        let index = this.fileInfos.findIndex(t => t.id === item.id);
        if (index === this.fileInfos.length - 1) {
            this.notify.warn(this._appLocalizationService.l('AlreadyBeTheLast'));
            return;
        }

        this.move(index, index + 1);
    }
}

